package uns.fit.gis.audio;
/*
 * cSound.java
 *
 * Created on March 4, 2008, 6:16 AM
 *
 * To change this template, choose Tools | Template Manager
 * and open the template in the editor.
 */
import java.io.ByteArrayInputStream;
import java.io.InputStream;

import javax.microedition.media.Manager;
import javax.microedition.media.MediaException;
import javax.microedition.media.Player;
import javax.microedition.media.PlayerListener;

import uns.fit.gis.MapDrawer;
import uns.fit.gis.Util;
import uns.fit.gis.VietnameseConverter;
import uns.fit.gis.fileio.FileWrapper;
/**
 *
 * @author Administrator
 */
public class Sound implements PlayerListener{
    
    /** Creates a new instance of cSound */
    public Sound() {
    }
    
//***************************************************************************
//** SOUNDS
//***************************************************************************

    
    public final static int MUSIC_GLOBAL_INDEX_START = 36;

    
    public final static int MUSIC_RESOURCE_COUNT = 15;
    public final static int SOUNDS_RESOURCE_COUNT = 23;
    
    public static final int     SOUND_START_GLOBAL_INDEX    = MUSIC_GLOBAL_INDEX_START;
    
    public static final int     SOUND_MUSIC_MARKER          = MUSIC_RESOURCE_COUNT;
    public static final int     NUM_SOUNDS                  = MUSIC_RESOURCE_COUNT + SOUNDS_RESOURCE_COUNT;

    public static boolean       m_bSoundsOn                 = false;
    public static int           m_iCurrentSound             = -1;



    public static long          game_lMusicDelay;
    public static boolean       m_bLastMusicLoop            = false;







//*************************************************************************
//** Sound.hpp
//**
//** Copyright @ Gameloft 2006
//** All rights reserved
//**
//***************************************************************************


    // Import the platform specific sound code which makes use of the appropriate API for that phone
    
//***************************************************************************
//** Vars for MIDP2 Sound
//***************************************************************************
    private static Player     m_pSound = null;
    private static byte _arrSoundIS[];// Array of sound input stream

    private static ByteArrayInputStream[]   arrSoundDataIS = new ByteArrayInputStream[NUM_SOUNDS]; 
    private static String []     soundType = new String[NUM_SOUNDS];


    public final static int MUSIC_TITLE_INDEX = 14;
    public final static int MUSIC_LVL_LOSE_INDEX = 12;
    public final static int SOUNDS_POP_0_INDEX = 0;
    public static final int  SOUND_POP  = SOUNDS_POP_0_INDEX + MUSIC_RESOURCE_COUNT;
//***************************************************************************
//** LoadSounds()
//***************************************************************************
    /*static void LoadBigSounds()
    {
        try
        {
            int i = MUSIC_TITLE_INDEX;
                    System.out.println("Load Big Sound");
                    if( arrSoundDataIS[i] == null )
                    {
                            System.out.println( "SOUND: Loading["+i+"]" ) ;

                            // Loads from 2 packages!!! SOUND package must follow directly the MUSIC package
                            //byte[] soundData = HaloMapCanvas.loadResourcefromFile(MUSIC_GLOBAL_INDEX_START + i, false);
                            byte[] soundData = HaloMapCanvas.loadResource(MUSIC_GLOBAL_INDEX_START + i, false);
                            if(soundData.length > 0)
                            {

                                    // This will tell us if its a WAV file (based on Spring Break by Nikolay Aleksiev)
                                    if (soundData[0] == 'R' &&
                                            soundData[1] == 'I' &&
                                            soundData[2] == 'F' &&
                                            soundData[3] == 'F')
                                    {
                                            soundType[i] = "audio/x-wav";						
                                    }
                                    // Check for AMR format
                                    else if(soundData[0] == '#' &&
                                                    soundData[1] == '!' &&
                                                    soundData[2] == 'A' &&
                                                    soundData[3] == 'M' &&
                                                    soundData[4] == 'R')
                                    {
                                            soundType[i] = "audio/amr";
                                    }
                                    //else its a midi file.
                                    else
                                    {
                                            soundType[i] = "audio/midi";
                                    }
                                    arrSoundDataIS[i] = new ByteArrayInputStream(soundData);
                                    arrSoundDataIS[i].reset();
                                    m_pSound = Manager.createPlayer(arrSoundDataIS[i],  soundType[i]);
                            }
                    }
                    else
                    {
                            System.out.println( "SOUND: Already loaded["+i+"]" ) ;
                    }
        }
        catch( Exception e )
        {
            System.out.println(  "Error Loading sound file: " + e.toString()  ) ;
        }
    }
*/

//***************************************************************************
//** LoadSounds()
//***************************************************************************
    public static void LoadSounds(int i,int p_RegionID)
    {
        //Make sure everything we were using is deallocated

        try
        {
            // Request what SOUNDS we want
            //int requestMask = 0xFFFFFFFF;

    //UNLOAD_NOT_USED_MUSIC
            //if( _arrSoundIS == null )
            {
                // If this is not requested it release it
                /*if( (requestMask&(1<<i)) == 0 )
                {
                    UnloadSound( );
                }
                // Check if its already loaded, if so don't do anything
                else*/
                {
                    System.out.println("Loading SOUND " + i );
                    m_tmpTest = "Loading SOUND " + i;
                    
                    _arrSoundIS = loadResourcefromFile(SOUND_START_GLOBAL_INDEX + i, true);
                    //_arrSoundIS = HaloMapCanvas.loadResource(SOUND_START_GLOBAL_INDEX + i, false);
                }
            }
        }
        catch( Exception e )
        {
            m_tmpTest = "Error Loading SOUND " + i;
            System.out.println(  "Error Loading sound file: " + e.toString()  ) ;
        }
    }

//***************************************************************************
//** UnloadSounds()
//***************************************************************************
    static void UnloadSounds ()
    {
        //Reset the sound so that nothing will play.
        m_iCurrentSound = -1;



        // Make sure there is something to deallocate
        if( _arrSoundIS != null )
        {
            UnloadSound();
        }
    }

//***************************************************************************
//** UnloadSound( int soundID )
//**   - Unloads 1 sound
//***************************************************************************
    public static void UnloadSound( )
    {
        if( _arrSoundIS != null  )
        {
            //Shut everything down, catching all exceptions
            _arrSoundIS = null;
                    System.gc();
        }
    }

//***************************************************************************
//** StopSounds()
//***************************************************************************
    public static void StopSounds()
    {
            if( m_iCurrentSound >= 0 )
        {
            try
            {
                            if (m_pSound != null)
                            {
                                    m_pSound.stop();


                    m_pSound.deallocate();

                                    m_pSound = null;
                                    System.gc();
                            }
            }
            catch( Exception e )
            {
                System.out.println(  "Error Stopping sound file: " + e.toString()  ) ;
                e.printStackTrace();
            }
        }
    }

    static void StopMusic()
    {

    }

//***************************************************************************
//** Check to see if some sound is playing
//***************************************************************************
    public static boolean bSoundPlaying()
    {
        if( m_iCurrentSound >= 0 )
        {
            if( m_pSound != null )
            {
                //Lets see if we are currently playing a sound
                if( m_pSound.getState() == Player.STARTED )
                {
                    return true;
                }
            }
        }

        return false;
    }

//***************************************************************************
//** PlaySound( int iSound )
//***************************************************************************
    static void PlaySound( int iSound, boolean bLoop, boolean bForceReset )
    {
        //TRACE("Playing sound " + iSound );

        //make sure what was passed in is valid
        if( iSound < 0 ||  _arrSoundIS == null ) // Nguyen 21/2/2008 changed
            return;    

      

        /*
        if( !m_bSoundsOn )
            return;
        */

        // If we are playing a new sound lets make sure to restart

        if( m_iCurrentSound != iSound )

        {
            bForceReset = true;
        }

        System.out.println( "Forcing restart = " + bForceReset  ) ;
        int checkSound = m_iCurrentSound;
        m_iCurrentSound = iSound;
        try
        {
            // Reset so that sound starts from the beggining...
            if( bForceReset)
            {
                            if( checkSound >= 0 && m_pSound != null)
                                    StopSounds();

                if(_arrSoundIS.length == 0)
                {
                    System.out.println( "Dummy sound: " + iSound ) ;
                    return;	// [Sinh.2008/02/01] dummy.xxx
                }

                // This will tell us if its a WAV file (based on Spring Break by Nikolay Aleksiev)
                if (_arrSoundIS[0] == 'R' &&
                        _arrSoundIS[1] == 'I' &&
                        _arrSoundIS[2] == 'F' &&
                        _arrSoundIS[3] == 'F')
                {
                        m_pSound = Manager.createPlayer(new ByteArrayInputStream(_arrSoundIS), "audio/x-wav");
                }
                // Check for AMR format
                else if(_arrSoundIS[0] == '#' &&
                                _arrSoundIS[1] == '!' &&
                                _arrSoundIS[2] == 'A' &&
                                _arrSoundIS[3] == 'M' &&
                                _arrSoundIS[4] == 'R')
                {
                        m_pSound = Manager.createPlayer(new ByteArrayInputStream( _arrSoundIS ), "audio/amr");
                }
                //else its a midi file.
                else
                {
                        m_pSound = Manager.createPlayer(new ByteArrayInputStream( _arrSoundIS ), "audio/midi");
                }

                m_pSound.realize();

                // Set the looping state and start location
                m_pSound.setLoopCount( bLoop ? -1 : 1);
                // BUG ON SOME PHONES: WILL STOP SOUND FROM PLAYING
                m_pSound.setMediaTime(0);
                //lets play!            
                m_pSound.start();
            }
            // else ALREADY PLAYING :)
        }
        catch( Exception e )
        {
            System.out.println(  "Error Starting sound file: " + iSound + e.toString()  ) ;
            e.printStackTrace();
        }
    }



    static int GetMusicTempo()
    {

        return -1;
    }

    static boolean SetMusicTempo (int p_iTempo)
    {

        return false;
    }



    

    public static void ResumeMusic()
    {

        PlaySound( m_iCurrentSound, m_bLastMusicLoop, true );

    }
    public static boolean m_isPlaySound = true;
    // If we are using a seperate thread for sound need some extra code...
	// With no sound server the call to PlaySound should directly call the real PlaySound.
	static void PlaySound(final int iSound )
	{
            System.out.println("Sound : " +iSound);
            if(m_isPlaySound)
            {
            	new Thread() {
                	public void run() {
                		LoadSounds(iSound,-1);
                		PlaySound(iSound, false, true);
                	}
                // By default do NOT LOOP, and RESET to start
                }.start();
                
                try {
					Thread.sleep(5000);
				}
				catch(InterruptedException ie) {
					ie.printStackTrace();
				}
				
            }
            //StopSounds();
	}
	
    ///////////////////////////////////////////////////
    /// Reading sound resource
    ///////////////////////////////////////////////////
    public static byte[]            haloMap_resourceIndex;
	public static InputStream       haloMap_resourceStream;
	public static int               haloMap_currentResourceCategory;
	public static int               haloMap_curResOff;
	
	public final static int RESOURCES_PACKAGES_OFFSET = 17941;
	public final static int RESOURCES_FILE_INDEX_SIZE = 17973;
	public final static int RESOURCES_PACKAGE_INDEX_BYTES = 1;
	public final static int RESOURCES_INDEX_BYTES = 1;
	public final static int RESOURCES_SIZE_BYTES = 4;
	public final static int RESOURCES_OFFSET_BYTES = 4;
	public final static int RESOURCES_FLAGS_BYTES = 1;
	public final static int RESOURCES_ALL_BYTES = (RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES + RESOURCES_SIZE_BYTES + RESOURCES_OFFSET_BYTES  + RESOURCES_FLAGS_BYTES);
	
	public static void generateFileIndex()
	{
		try
		{
		    InputStream stream = MapDrawer.getMidlet().getClass().getResourceAsStream("/0");
		    haloMap_resourceIndex = new byte[RESOURCES_FILE_INDEX_SIZE];
		    stream.read(haloMap_resourceIndex, 0, RESOURCES_FILE_INDEX_SIZE);
		    stream.close();
		}
		catch   (Exception e)
		{
		    e.printStackTrace();
		}
	}
	
	public static javax.microedition.io.file.FileConnection fc = null;
	public static java.io.InputStream os = null;
	public static javax.microedition.io.Connection c = null;
	
	public static byte[] loadResourcefromFile(int res, boolean close_file)
	{
	
	    if( haloMap_resourceIndex == null )
	    {
	        generateFileIndex();
	    }
	
	    int category = haloMap_resourceIndex[( res ) * RESOURCES_ALL_BYTES] ;
	    int offset   = ((( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES + RESOURCES_SIZE_BYTES )] & 0xFF) << 24) | (( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES + RESOURCES_SIZE_BYTES ) + 1] & 0xFF) << 16) | (( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES + RESOURCES_SIZE_BYTES ) + 2] & 0xFF) << 8) | ( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES + RESOURCES_SIZE_BYTES ) + 3] & 0xFF))  ;
	    int size     = ((( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES )] & 0xFF) << 24) | (( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES ) + 1] & 0xFF) << 16) | (( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES ) + 2] & 0xFF) << 8) | ( haloMap_resourceIndex [(  ( res ) * RESOURCES_ALL_BYTES + RESOURCES_PACKAGE_INDEX_BYTES + RESOURCES_INDEX_BYTES ) + 3] & 0xFF))  ;
	
	
	    //if(os==null)
	    {
	        try {
	            //c = javax.microedition.io.Connector.open("file:///" + "c:/Other/SOUNDS", javax.microedition.io.Connector.READ);
	        	c = javax.microedition.io.Connector.open("file:///root1/SOUNDS", javax.microedition.io.Connector.READ);
	            fc = (javax.microedition.io.file.FileConnection) c;
	
	            os = fc.openInputStream();
	            haloMap_resourceStream = os;
	            System.out.println( "----======== Just opened cat: SOUNDS for res " + res  ) ;
	            haloMap_curResOff = 0;
	            System.out.println("None Error on reading file at Phone!");
	        }
	        catch(Exception e)
	        {
	            System.out.println("Error on reading file at Phone!");
	        }
	    }
	
	    int skip_value = offset - haloMap_curResOff;
	
	    if(skip_value >= 0)
	    {
	        try
	        {
	            haloMap_resourceStream.skip(skip_value);
	            byte[] resData = new byte[size];
	            haloMap_resourceStream.read(resData, 0, size);
	            if(close_file)
	            {
	                closeFileStream();
	            }
	            else
	            {
	                haloMap_curResOff += (skip_value + size);
	            }
	            System.out.println("DATA " + resData.length);
	            return resData;
	        }
	        catch( Exception e )
	        {
	        	e.printStackTrace();
	        }
	    }
	    System.out.println( "OFFSET IS NEGATIVE!!!!!!!!!!!!" ) ;
	    return null;
	}

	public static void closeFileStream()
	{
		try
		{
		    if( haloMap_resourceStream != null )
		    {
		        haloMap_resourceStream.close();
		    }
		}
		catch( Exception e )
		{
		}
		
		haloMap_resourceStream = null;
		System.gc();
		
		haloMap_curResOff = 0;
	}

	public static String m_tmpTest = "NULL";

	public void playerUpdate(Player player, String event, Object eventData) {
		if (event == (PlayerListener.VOLUME_CHANGED)) {

		}
		else if (event == (PlayerListener.STOPPED)) {

		}
		else if (event == (PlayerListener.STARTED)) {

		}
		else if (event == (PlayerListener.END_OF_MEDIA)) {
			try {
				m_pSound.stop();
			}
			catch(MediaException me) {
				me.printStackTrace();
			}
		}
		else if (event == (PlayerListener.CLOSED)) {

		}
		else if (event == (PlayerListener.ERROR)) {

		}
	}
	
	public static void readString(final String[] strs) {
		try {
			new Thread() {
				public void run() {
					String str = null;
					String dir = Util.SOUND_FOLDER;
					if(!FileWrapper.exists(dir)) {
						dir = System.getProperty("fileconn.dir.memorycard");
						if(dir == null)
							dir = "file:///root1/";
						dir += "Test2/sound/";
					}
					Player player = null;
					PlayerThread playerThread = null;
					byte[] bytes;
					for(int i = 0; i < strs.length; i ++) {
						str = dir + VietnameseConverter.toTextNotMarked(strs[i].replace(' ', '_')) + ".wav";
						System.out.println(str);
						bytes = FileWrapper.load(str);
						if(bytes != null) {
							playerThread = new PlayerThread(new ByteArrayInputStream(bytes), "audio/X-wav");
							playerThread.start();
							
							try {
								Thread.sleep(3000);
							} catch (InterruptedException e) {
								// TODO Auto-generated catch block
								e.printStackTrace();
							}
						}
					}
				}
			}.start();
		}
		catch(Exception e) {
			e.printStackTrace();
		}
	}
}
